package cn.iocoder.yudao.module.scrm.aop;

import cn.iocoder.yudao.module.scrm.annotations.FieldCompareValidator;
import cn.iocoder.yudao.module.scrm.annotations.FieldCompareValidators;
import cn.iocoder.yudao.module.scrm.enums.common.CrmBizTypeEnum;
import cn.iocoder.yudao.module.scrm.strategy.CompareStrategy;
import cn.iocoder.yudao.module.scrm.strategy.CompareStrategyFactory;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.scrm.enums.ErrorCodeConstants.*;

/**
 * 处理字段比较验证的切面类。
 * <p>
 * 该类是一个切面类，用于在方法执行之前，基于自定义注解 {@link FieldCompareValidators} 提供的配置信息，
 * 执行字段比较验证逻辑。通过切面技术，实现了在运行时动态地插入验证逻辑，从而增强系统的灵活性和可维护性。
 * </p>
 *
 * @Author LiZhiMin
 * @Date 2024/8/31 17:38
 */
@Aspect
@Component
@Slf4j
public class FieldCompareValidatorAspect {

    @Autowired
    private CompareStrategyFactory compareStrategyFactory;

    /**
     * 切点方法，用于在被 {@link FieldCompareValidators} 注解标记的方法执行之前触发。
     * <p>
     * 从注解中提取字段比较配置，并根据这些配置选择并执行相应的比较策略。
     * 该方法获取方法参数，提取比较需要的字段信息，并通过 {@link CompareStrategyFactory} 获取对应的比较策略进行验证。
     * </p>
     *
     * @param joinPoint              连接点，提供了方法执行的信息和上下文。
     * @param fieldCompareValidators 自定义注解 {@link FieldCompareValidators}，提供字段比较的配置信息。
     */
    @Before("@annotation(fieldCompareValidators)")
    public void pointcut(JoinPoint joinPoint, FieldCompareValidators fieldCompareValidators) throws NoSuchFieldException, IllegalAccessException {
        // 获取方法参数
        Object[] args = joinPoint.getArgs();
        // 从注解中提取主表枚举类型
        CrmBizTypeEnum crmBizTypeEnumForeignKey = fieldCompareValidators.foreignKeyType();
        // 获取要查询的主表字段名
        String foreignKeyFieldName = fieldCompareValidators.foreignKeyFieldName().getFieldName();

        // 遍历所有字段比较验证配置
        for (FieldCompareValidator compareValidator : fieldCompareValidators.fieldCompareValidator()) {
            // 获取比较字段名和关联表枚举类型
            String majorKeyFieldName = compareValidator.majorJeyFieldName().getFieldName();
            CrmBizTypeEnum crmBizTypeEnumMajorKey = compareValidator.majorJeyType();

            // 从工厂获取对应的比较策略
            CompareStrategy strategy = compareStrategyFactory.getStrategy(crmBizTypeEnumForeignKey, crmBizTypeEnumMajorKey);

            if (strategy != null) {
                // 执行策略进行字段比较验证
                strategy.handle(args[0], foreignKeyFieldName, majorKeyFieldName,crmBizTypeEnumMajorKey);
            } else {
                // 如果未找到对应的策略，则抛出异常
                throw exception(COMPARE_STRATEGY_TYPE_NOT_NULL);
            }
        }
    }
}
